/*-----------------------------------------------------------------------------
	The contents of this file are subject to the Mozilla Public License
	Version 1.1 (the "License"); you may not use this file except in
	compliance with the License.You may obtain a copy of the License at
	http://www.mozilla.org/MPL/MPL-1.1.html
	
	Software distributed under the License is distributed on an "AS IS"
	basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
	License for the specific language governing rights and limitations
	under the License.
	
	The Original Code is Fever Framework code.
	
	The Initial Developer of the Original Code is Romain Ecarnot.
	Portions created by Initial Developer are Copyright (C) 2006
	the Initial Developer. All Rights Reserved.
	
	Contributor(s):
	
	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
-----------------------------------------------------------------------------*/

import com.bourre.data.collections.IndexedArray;
import com.bourre.events.EventBroadcaster;
import com.bourre.events.EventType;

import fever.data.file.FileFilter;
import fever.data.file.FileUploaderEvent;
import fever.Fever;
import fever.log.FeverDebug;

import flash.net.FileReference;

/**
 * Manages basic file uploading using Adobe FileReference object.
 * 
 * <p>Real basic implementation.
 *
 * @author Romain Ecarnot
 */
class fever.data.file.FileUploader
{
	//-------------------------------------------------------------------------
	// Events definition
	//-------------------------------------------------------------------------
	
	/** Triggered when user select file to upload. */
	public static var UPLOAD_SELECT : EventType = FileUploaderEvent.UPLOAD_SELECT;
	
	/** Triggered when upload start. */
	public static var UPLOAD_START : EventType = FileUploaderEvent.UPLOAD_START;
	
	/** Triggered during upload progress. */
	public static var UPLOAD_PROGRESS : EventType = FileUploaderEvent.UPLOAD_PROGRESS;
	
	/** Trigerred when upload is finished. */
	public static var UPLOAD_COMPLETE : EventType = FileUploaderEvent.UPLOAD_COMPLETE;
	
	/** Trigerred when error occured during upload process. */
	public static var UPLOAD_ERROR : EventType = FileUploaderEvent.UPLOAD_ERROR;
	
		
	//-------------------------------------------------------------------------
	// Private properties
	//-------------------------------------------------------------------------
	
	private static var _instance : FileUploader;
	
	private var _fileRef : FileReference;
	private var _maxSize : Number;
	private var _oEB : EventBroadcaster;
	private var _filters : IndexedArray;
	private var _target : String;
	
	
	//-------------------------------------------------------------------------
	// Public Properties
	//-------------------------------------------------------------------------
	
	/** Default max size for compliant file. */
	public static var DEFAULT_MAX_SIZE : Number = 6000000;
		
	
	//-------------------------------------------------------------------------
	// Public API
	//-------------------------------------------------------------------------
	
	/**
	 * Returns {@link FileUploader} instance.
	 */
	public static function getInstance() : FileUploader
	{
		if( !_instance ) _instance = new FileUploader();
		return _instance;	
	}
	
	/**
	 * Constructor.
	 */
	public function FileUploader()
	{
		_oEB = new EventBroadcaster( this );
		
		_filters = new IndexedArray();
		
		_fileRef = new FileReference();
		_fileRef.addListener( this );
		
		_maxSize = DEFAULT_MAX_SIZE;
		
		_target = null;
	}
	
	/**
	 * Adds {@link fever.data.file.FileFilter} filter for dialog.
	 */
	public function addFilter( filter : FileFilter ) : Boolean
	{
		return _filters.push( filter.toFileReferenceFilter() );
	}
	
	/**
	 * Removes {@link fever.data.file.FileFilter} filter from dialog.
	 */
	public function removeFilter( filter : FileFilter ) : Boolean
	{
		return _filters.remove( filter.toFileReferenceFilter() );
	}
	
	/**
	 * Removes all {@link fever.data.file.FileFilter} filter.
	 */
	public function cleanFilter() : Void
	{
		_filters.init();
	}
	
	/**
	 * Sets the possible max size of uploaded file.
	 */
	public function setMaxFileSize( n : Number ) : Void
	{
		if( n > 0 ) _maxSize = n;
	}
	
	/**
	 * Returns the file size limit.
	 */
	public function getMaxFileSize() : Number
	{
		return _maxSize;
	}
	
	/**
	 * Adds passed-in {@code listener} for receiving passed-in {@code type} event type.
	 * 
	 * @param type Name of the Event.
	 * @param listener Listener object.
	 */
	public function addEventListener( type : EventType, listener ) : Void
	{
		_oEB.addEventListener.apply( _oEB, arguments );	
	}
	
	/**
	 * Removes passed-in {@code listener} for receiving passed-in {@code type} event type.
	 * 
	 * @param type Name of the Event.
	 * @param listener Listener object.
	 */
	public function removeEventListener( type : EventType, listener ) : Void
	{
		_oEB.removeEventListener( type, listener );
	}
	
	/**
	 * Clears listeners list.
	 */
	public function clearListeners() : Void
	{
		_oEB.removeAllListeners();	
	}
	
	/**
	 * Starts upload process
	 * 
	 * @param targetPath where to upload file on server
	 */
	public function browse( targetPath : String ) : Void
	{
		_target = targetPath;
		
		if( _filters.isEmpty() ) _fileRef.browse();
		else _fileRef.browse( _filters.getElements() );
	}
	
	
	
	//-------------------------------------------------------------------------
	// Private implementation
	//-------------------------------------------------------------------------
	
	private function onSelect( file : FileReference ) : Void
	{
		if( file.size <= _maxSize )
		{
			var dest : String = Fever.application.url + "/uploader.php";
			dest += ( _target ) ? ( "?path=" + _target ) : "";
			
			if( !file.upload( dest ) ) 
			{
        		onIOError( file, "Upload dialog failed to open." );
    		}
		}
		else onIOError( file, "too bytes too load" );
	}
	
	private function onCancel( file : FileReference ) : Void
	{
    	FeverDebug.DEBUG( "cancel" );
	}
	
	private function onOpen( file : FileReference ) : Void
	{
		_oEB.broadcastEvent( new FileUploaderEvent( UPLOAD_START, file.name, file.size, 0, "open" ) );
	}
	
	private function onProgress ( file : FileReference, bytesLoaded : Number, bytesTotal : Number) : Void
	{
	 	_oEB.broadcastEvent( new FileUploaderEvent( UPLOAD_PROGRESS, file.name, file.size, bytesLoaded, "progress" ) );
	}
	
	private function onComplete( file : FileReference ) : Void
	{
		_oEB.broadcastEvent( new FileUploaderEvent( UPLOAD_COMPLETE, file.name, file.size, file.size, "complete" ) );
	}
	
	private function onHTTPError( file : FileReference, httpErreur : Number ) : Void
	{
		_oEB.broadcastEvent( new FileUploaderEvent( UPLOAD_ERROR, file.name, file.size, 0, httpErreur.toString() ) );	
	}
	
	private function onIOError( file : FileReference, erreur : String ) : Void
	{
		_oEB.broadcastEvent( new FileUploaderEvent( UPLOAD_ERROR, file.name, file.size, 0, erreur ) );
	}
	
	private function onSecurityError( file : FileReference, errorString : String ) : Void
	{
		_oEB.broadcastEvent( new FileUploaderEvent( UPLOAD_ERROR, file.name, file.size, 0, errorString ) );
	}
}